package factories;

import models.PlotCurve;
import models.PlotModel;
import models.statistics.ICompressionStats;
import models.statistics.ISLPCompressionStats;
import models.statistics.ISLPUsingAVLCompressionStats;

import java.util.ArrayList;

public class PlotFactory implements IPlotFactory {
    private static final int MB = 1024 * 1024;
    private static final int Second = 1000;

    @Override
    public PlotModel createAVLRotationsPlot(ISLPUsingAVLCompressionStats[]... stats) {
        ArrayList<PlotCurve> curves = new ArrayList<PlotCurve>();
        for (int i = 0; i < stats.length; i++) {
            if (stats[i].length > 0) {
                int[][] points = new int[stats[i].length][2];
                for (int j = 0; j < stats[i].length; j++) {
                    points[j][0] = convertLongToInt(stats[i][j].calcTextSize(MB));
                    points[j][1] = convertLongToInt(stats[i][j].getAVLRotationsNumber(1));
                }
                curves.add(new PlotCurve(points, stats[i][0].algorithmType()));
            }
        }
        return createPlotModel(curves, "Mb", "AVL-rotations number");
    }

    @Override
    public PlotModel createSLPCompressionTimePlot(ISLPCompressionStats[]... stats) {
        ArrayList<PlotCurve> curves = new ArrayList<PlotCurve>();

        for (int i = 0; i < stats.length; i++) {
            if (stats[i].length > 0) {
                int[][] points = new int[stats[i].length][2];
                for (int j = 0; j < stats[i].length; j++) {
                    points[j][0] = convertLongToInt(stats[i][j].calcTextSize(MB));
                    points[j][1] = convertLongToInt(stats[i][j].calcCompressionTime(Second));
                }

                curves.add(new PlotCurve(points, stats[i][0].algorithmType()));
            }
        }
        return createPlotModel(curves, "Mb", "Seconds");
    }

    @Override
    public PlotModel createCompressionRatePlot(ICompressionStats[]... stats) {
        ArrayList<PlotCurve> curves = new ArrayList<PlotCurve>();
        for (int i = 0; i < stats.length; i++) {
            if (stats[i].length > 0) {
                int[][] points = new int[stats[i].length][2];
                for (int j = 0; j < stats[i].length; j++) {
                    points[j][0] = convertLongToInt(stats[i][j].calcTextSize(MB));
                    points[j][1] = (int) stats[i][j].calcCompressionRate();
                }
                curves.add(new PlotCurve(points, stats[i][0].algorithmType()));
            }
        }
        return createPlotModel(curves, "Mb", "Compression rate");
    }

    private static PlotModel createPlotModel(ArrayList<PlotCurve> list, String xLabel, String yLabel) {
        PlotCurve[] array = new PlotCurve[list.size()];
        list.toArray(array);
        return new PlotModel(array, xLabel, yLabel);
    }

    private static int convertLongToInt(long value) {
        if (value > Integer.MAX_VALUE)
            throw new RuntimeException("Fail to convert " + String.valueOf(value) + " to int");
        return (int) value;
    }
}
